import json
from _decimal import Decimal

from django import http
from django.core.paginator import Paginator
from django.shortcuts import render

# Create your views here.
from django.utils import timezone
from django.views import View
from django_redis import get_redis_connection
from django.db import transaction
from areas.models import Address
from goods.models import SKU
from orders.models import OrderInfo, OrderGoods
from users.views import LoginRequiedView
from utils.response_code import RET


class OrderSettlementView(LoginRequiedView):
    def get(self, request):
        # 获取订单提交页面
        # 1, 初始化数据
        user = request.user

        # 2, 处理业务逻辑
        # 获取地址信息
        addresses = user.addresses.filter(is_deleted=False)
        # [<Address:1>,<Address:2>,],
        # <Address:1>:{"province":'','city':'', 'disc':'', 'receiver':''}
        # addresses = Address.objects.filter(user=user)

        # 准备加总数据
        total_count = 0
        total_amount = Decimal(0.0)
        freight = Decimal(10.0)
        # 获取商品数据
        # 从redis购物车中获取勾选的商品数据
        redis_conn = get_redis_connection('carts')
        carts_dict = redis_conn.hgetall('carts_%s' % user.id)
        # {sku_id: 1,}
        selected_list = redis_conn.smembers('selected_%s' % user.id)

        # for sku_id, count in carts_dict.items():
        #     if sku_id in selected_list:
        #         pass
        #     pass
        skus = []
        for sku_id in selected_list:
            sku = SKU.objects.get(id=sku_id)
            sku_data = {
                "id": sku.id,
                "name": sku.name,
                "price": str(sku.price),  # Decimal  -> str  不会丢失 小数点
                "count": int(carts_dict[sku_id]),
                "amount": sku.price * int(carts_dict[sku_id]),
                "default_image_url": sku.default_image_url.url,
            }
            skus.append(sku_data)
            total_count += sku_data['count']
            total_amount += sku_data['amount']

        payment_amount = total_amount + freight

        context = {
            'addresses': addresses,
            'default_address_id': user.default_address_id,
            'skus': skus,
            'total_count': total_count,
            'total_amount': total_amount,
            'freight': freight,
            'payment_amount': payment_amount,

        }
        # 3, 返回响应
        return render(request, 'place_order.html', context=context)
        pass


class OrderCommitView(LoginRequiedView):
    def post(self, request):
        # 保存订单信息
        # 1, 初始化数据
        user = request.user
        data = json.loads(request.body.decode())
        address_id = data.get('address_id')
        pay_method = data.get('pay_method')  # 1, 2

        # 2.1为空校验
        if not all([address_id, pay_method]):
            return http.HttpResponseForbidden("参数不全")

        try:
            address = Address.objects.get(id=address_id)
        except Exception as e:
            return http.JsonResponse({'code': RET.PARAMERR, 'errmsg': '地址信息错误'})

        # if not pay_method in [OrderInfo.PAY_METHODS_ENUM['CASH'], OrderInfo.PAY_METHODS_ENUM['ALIPAY']]:
        #     return http.JsonResponse({'code': RET.PARAMERR,'errmsg': '支付方式有误'})
        if not pay_method in OrderInfo.PAY_METHODS_ENUM.values():
            return http.JsonResponse({'code': RET.PARAMERR, 'errmsg': '支付方式有误'})

        # 判断一下购物车的信息
        redis_conn = get_redis_connection('carts')
        carts_dict = redis_conn.hgetall('carts_%s' % user.id)
        selected_list = redis_conn.smembers('selected_%s' % user.id)
        if not selected_list:
            return http.JsonResponse({'code': RET.DATAERR, 'errmsg': '购物车信息有误'})

        # 2, 处理业务逻辑
        # 准备数据
        # 生成订单编号：年月日时分秒 + 9位用户编号
        order_id = timezone.localtime().strftime('%Y%m%d%H%M%S') + '%09d' % user.id
        total_count = 0
        total_amount = Decimal(0)
        freight = Decimal(10)
        pay_method = pay_method

        if pay_method == OrderInfo.PAY_METHODS_ENUM['CASH']:
            status = OrderInfo.ORDER_STATUS_ENUM['UNSEND']
        else:
            status = OrderInfo.ORDER_STATUS_ENUM['UNPAID']

        with transaction.atomic():
            save_id = transaction.savepoint()
            try:
                order = OrderInfo.objects.create(
                    order_id=order_id,
                    user=user,
                    address=address,
                    total_count=total_count,
                    total_amount=total_amount,
                    freight=freight,
                    pay_method=pay_method,
                    status=status
                )

                # 保存订单商品信息
                for sku_id in selected_list:
                    while True:
                        sku = SKU.objects.get(id=sku_id)
                        sku_count = int(carts_dict[sku_id])

                        # 判断库存是否足够
                        if sku_count > sku.stock:
                            transaction.savepoint_rollback(save_id)
                            return http.JsonResponse({'code': RET.DATAERR, 'errmsg': '库存不足'})
                        # 保存一下原始值
                        old_sku_stock = sku.stock
                        old_sku_sales = sku.sales

                        # import time
                        # time.sleep(5)

                        # # 更新库存和销量
                        # sku.sales += sku_count
                        # sku.stock -= sku_count
                        # sku.save()

                        res = SKU.objects.filter(id=sku_id, stock=old_sku_stock, sales=old_sku_sales
                                           ).update(stock=old_sku_stock - sku_count, sales=old_sku_sales + sku_count)

                        if res == 0:
                            continue
                            # transaction.savepoint_rollback(save_id)
                            # return http.JsonResponse({'code': RET.DATAERR,'errmsg': '系统繁忙,稍后再试'})

                        break

                    # 保存订单商品
                    order_goods = OrderGoods.objects.create(
                        order=order,
                        sku=sku,
                        count=sku_count,
                        price=sku.price,
                    )

                    # 更新订单统计数据
                    order.total_count += order_goods.count
                    order.total_amount += order_goods.count * order_goods.price

                # 保存订单数据
                order.save()
            except Exception as e:
                transaction.savepoint_rollback(save_id)
                return http.JsonResponse({'code': RET.DBERR, 'errmsg': '订单提交失败'})
            transaction.savepoint_commit(save_id)

        # 清理购物车
        redis_conn.hdel('carts_%s' % user.id, *selected_list)
        redis_conn.srem('selected_%s' % user.id, *selected_list)

        res = {
            'code': RET.OK,
            'errmsg': '成功',
            'order_id': order_id
        }
        return http.JsonResponse(res)
        # 3, 返回响应
        pass


class OrderSuccessView(LoginRequiedView):
    def get(self, request):
        # 展示下订单成功页面
        # 1, 初始化数据
        """?order_id=20191013010544000000001&payment_amount=3798&pay_method=2"""
        user = request.user
        order_id = request.GET.get('order_id')
        payment_amount = request.GET.get('payment_amount')
        pay_method = request.GET.get('pay_method')  # str

        if not all([order_id, payment_amount, pay_method]):
            return http.HttpResponseForbidden('参数不全')

        # 判断order_id是否正确
        try:
            OrderInfo.objects.get(order_id=order_id)
        except Exception as e:
            return http.HttpResponseForbidden('订单信息有误')

        # 2, 处理业务逻辑
        context = {
            'payment_amount': payment_amount,
            'order_id': order_id,
            'pay_method': pay_method
        }

        # 3, 返回响应
        return render(request, 'order_success.html', context=context)
        pass


class UserOrderInfoView(LoginRequiedView):
    def get(self, request, page_num):
        # 获取我的订单页面
        # 1, 初始化数据
        user = request.user

        # 2, 处理业务逻辑
        # OrderInfo.objects.filter()
        order_all = user.orderinfo_set.all()
        """
        (
        (1, "货到付款"),
        (2, "支付宝"),
        )
    """
        pay_method_dict = {item[0]: item[1] for item in OrderInfo.PAY_METHOD_CHOICES}
        # {1:"货到付款",2:"支付宝"}
        status_name_dict = {item[0]: item[1] for item in OrderInfo.ORDER_STATUS_CHOICES}
        # {1:"待支付",2: "待发货",.....}
        order_list = []
        for order in order_all:
            order_data = {
                "order_id": order.order_id,
                "create_time": order.create_time.strftime('%Y-%m-%d %H:%M:%S'),
                "total_amount": order.total_amount,
                "freight": order.freight,
                # "pay_method_name":OrderInfo.PAY_METHOD_CHOICES[order.pay_method-1][1],
                "pay_method_name": pay_method_dict.get(order.pay_method),
                "status": order.status,
                "status_name": status_name_dict.get(order.status),
                "sku_list": [],
            }

            order_sku_all = order.skus.all()
            for order_sku in order_sku_all:
                order_sku_data = {
                    "default_image_url":order_sku.sku.default_image_url.url,
                    "name":order_sku.sku.name,
                    "price":order_sku.price,
                    'count':order_sku.count,
                    'amount':order_sku.price*order_sku.count,
                }
                order_data["sku_list"].append(order_sku_data)


            order_list.append(order_data)

        p = Paginator(order_list,2)
        current_page = p.page(int(page_num))

        context = {
            "page_orders":current_page.object_list,
            "current_page": current_page.number,
            "total_page": p.num_pages,
        }
        return render(request, 'user_center_order.html', context=context)

        # 3, 返回响应
        pass


class OrderCommentView(LoginRequiedView):
    def get(self, request):
        """展示商品评价页面"""
        # 接收参数
        order_id = request.GET.get('order_id')
        # 校验参数
        try:
            OrderInfo.objects.get(order_id=order_id, user=request.user)
        except OrderInfo.DoesNotExist:
            return http.HttpResponseNotFound('订单不存在')

        # 查询订单中未被评价的商品信息
        try:
            uncomment_goods = OrderGoods.objects.filter(order_id=order_id, is_commented=False)
        except Exception:
            return http.HttpResponseServerError('订单商品信息出错')

        # 构造待评价商品数据
        uncomment_goods_list = []
        for goods in uncomment_goods:
            goods_data={
                'order_id':goods.order.order_id,
                'sku_id':goods.sku.id,
                'name':goods.sku.name,
                'price':str(goods.price),
                'default_image_url':goods.sku.default_image_url.url,
                # 'comment':goods.comment,
                # 'score':goods.score,
                # 'is_anonymous':str(goods.is_anonymous),
            }

            uncomment_goods_list.append(goods_data)

        # 渲染模板
        context = {
            'uncomment_goods_list': json.dumps(uncomment_goods_list)
        }
        return render(request, 'goods_judge.html', context)

    def post(self,request):
        """评价订单商品"""
        # 接收参数
        json_dict = json.loads(request.body.decode())
        order_id = json_dict.get('order_id')
        sku_id = json_dict.get('sku_id')  # order_goods
        score = json_dict.get('score')
        comment = json_dict.get('comment')
        is_anonymous = json_dict.get('is_anonymous')
        # 校验参数
        if not all([order_id, sku_id, score, comment]):
            return http.HttpResponseForbidden('缺少必传参数')
        try:
            OrderInfo.objects.filter(order_id=order_id, user=request.user,
                                     status=OrderInfo.ORDER_STATUS_ENUM['UNCOMMENT'])
        except OrderInfo.DoesNotExist:
            return http.HttpResponseForbidden('参数order_id错误')
        try:
            sku = SKU.objects.get(id=sku_id)
        except SKU.DoesNotExist:
            return http.HttpResponseForbidden('参数sku_id错误')
        if is_anonymous:
            if not isinstance(is_anonymous, bool):
                return http.HttpResponseForbidden('参数is_anonymous错误')

        # 保存订单商品评价数据
        OrderGoods.objects.filter(order_id=order_id, sku_id=sku_id, is_commented=False).update(
            comment=comment,
            score=score,
            is_anonymous=is_anonymous,
            is_commented=True
        )

        # 累计评论数据
        sku.comments += 1
        sku.save()
        sku.spu.comments += 1
        sku.spu.save()

        # 如果所有订单商品都已评价，则修改订单状态为已完成
        if OrderGoods.objects.filter(order_id=order_id, is_commented=False).count() == 0:
            OrderInfo.objects.filter(order_id=order_id).update(status=OrderInfo.ORDER_STATUS_ENUM['FINISHED'])

        return http.JsonResponse({'code': RET.OK, 'errmsg': '评价成功'})